/*
 * @(#)MaintFormSubmissionAction.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.form.web;

import java.io.IOException;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.quartz.JobDataMap;

import com.dcivision.dms.bean.DmsDocument;
import com.dcivision.dms.core.DocumentRetrievalManager;
import com.dcivision.dms.dao.DmsDocumentDAObject;
import com.dcivision.form.bean.FormData;
import com.dcivision.form.bean.FormDataElement;
import com.dcivision.form.bean.FormElement;
import com.dcivision.form.bean.FormPage;
import com.dcivision.form.bean.FormRecord;
import com.dcivision.form.bean.FormSubmission;
import com.dcivision.form.bean.FormSubmissionHtml;
import com.dcivision.form.core.FormHttpOperation;
import com.dcivision.form.core.FormSubmissionManager;
import com.dcivision.form.dao.FormDataDAObject;
import com.dcivision.form.dao.FormDataElementDAObject;
import com.dcivision.form.dao.FormElementDAObject;
import com.dcivision.form.dao.FormFileAttachmentDAObject;
import com.dcivision.form.dao.FormPageDAObject;
import com.dcivision.form.dao.FormRecordDAObject;
import com.dcivision.form.dao.FormSubmissionDAObject;
import com.dcivision.form.dao.FormSubmissionHtmlDAObject;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.Crypt;
import com.dcivision.framework.DataSourceFactory;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.MessageResourcesFactory;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemFunctionConstant;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;
import com.dcivision.framework.web.AbstractActionForm;
import com.dcivision.framework.web.AbstractMaintAction;
import com.dcivision.framework.web.WorkflowActionFormInterface;
import com.dcivision.user.bean.UserDelegation;
import com.dcivision.user.dao.UserDelegationDAObject;
import com.dcivision.workflow.WorkflowOperationConstant;
import com.dcivision.workflow.bean.MtmWfProgressAccessForm;
import com.dcivision.workflow.bean.MtmWorkflowProgressSystemObject;
import com.dcivision.workflow.bean.WorkflowProgress;
import com.dcivision.workflow.bean.WorkflowProgressAttachment;
import com.dcivision.workflow.bean.WorkflowStep;
import com.dcivision.workflow.core.WorkflowPermissionManager;
import com.dcivision.workflow.core.WorkflowStepManager;
import com.dcivision.workflow.dao.MtmWfProgressAccessFormDAObject;
import com.dcivision.workflow.dao.MtmWorkflowProgressSystemObjectDAObject;
import com.dcivision.workflow.dao.WorkflowProgressDAObject;
import com.dcivision.workflow.dao.WorkflowStepDAObject;

/**
  MaintFormSubmissionAction.java

  This class is for maint user record.

    @author          Scott Tong
    @company         DCIVision Limited
    @creation date   07/01/2003
    @version         $Revision: 1.137.2.4 $
*/

public class MaintFormSubmissionAction extends AbstractMaintAction implements com.dcivision.framework.web.WorkflowActionInterface {

  public static final String REVISION = "$Revision: 1.137.2.4 $";

  protected String listName = "";
  private Integer formPageID = null;


  public MaintFormSubmissionAction() {
    super();
  }

  /**
   * getMajorDAOClassName
   *
   * @return  The class name of the major DAObject will be used in this action.
   */
  public String getMajorDAOClassName() {
    return("com.dcivision.form.dao.FormSubmissionDAObject");
  }

  /**
   * getFunctionCode
   *
   * @return  The corresponding system function code of action.
   */
  public String getFunctionCode() {
    return(SystemFunctionConstant.FORM_SUBMISSION);
  }

  public void selectRecord(ActionMapping mapping,
                           AbstractActionForm form,
                           HttpServletRequest request,
                           HttpServletResponse response)
      throws ApplicationException {
   try {
     MaintFormSubmissionForm formSubmissionForm = (MaintFormSubmissionForm)form;
     DmsDocumentDAObject dmsDocDAO = new DmsDocumentDAObject(this.getSessionContainer(request), this.getConnection(request));
     WorkflowStepDAObject workflowStepDAO = new WorkflowStepDAObject(this.getSessionContainer(request), this.getConnection(request));
     FormRecordDAObject formRecordDAO = new FormRecordDAObject(this.getSessionContainer(request), this.getConnection(request));
     FormPageDAObject formPageDAO = new FormPageDAObject(this.getSessionContainer(request), this.getConnection(request));
     FormSubmissionDAObject formSubmissionDAO = new FormSubmissionDAObject(this.getSessionContainer(request), this.getConnection(request));
     FormDataElementDAObject formDataElementDAO = new FormDataElementDAObject(this.getSessionContainer(request), this.getConnection(request));
     DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(this.getSessionContainer(request), this.getConnection(request));
     int pageNo = 0;

     if(!Utility.isEmpty(request.getParameter("formPageNo")) && !"null".equals(request.getParameter("formPageNo")) ){
       pageNo = Integer.parseInt(request.getParameter("formPageNo"));
     }

     Integer formRecordID = TextUtility.parseIntegerObj(formSubmissionForm.getFormRecordID());
     Integer workflowStepID = !Utility.isEmpty(request.getParameter("workflowStepID")) && !"null".equals(request.getParameter("workflowStepID")) ? new Integer(request.getParameter("workflowStepID")) : new Integer(0);
     boolean isRightWorkflowStep = workflowStepID.intValue()==0
                                     && !Utility.isEmpty(formSubmissionForm.getWorkflowRecordID())
                                     && !"null".equals(formSubmissionForm.getWorkflowRecordID())
                                     && !"0".equals(formSubmissionForm.getWorkflowRecordID())
                                     && !"-1".equals(formSubmissionForm.getWorkflowRecordID());
    if (isRightWorkflowStep){
      if (!Utility.isEmpty(request.getParameter("formDataSeq")) && !"null".equals(request.getParameter("formDataSeq"))){
        FormDataElement formDataElement = (FormDataElement)formDataElementDAO.getFormDataElementBySeq(new Integer(request.getParameter("formDataSeq")));
        Integer progressID = formDataElement.getWorkflowProgressID();
        if (!Utility.isEmpty(progressID) && !"null".equals(progressID)){
          WorkflowStep workflowStep = (WorkflowStep)workflowStepDAO.getStepByWorkflowProgress(progressID);
          workflowStepID = workflowStep.getID();
        }else if(!Utility.isEmpty(formDataElement.getSubmitFlag()) && !FormSubmission.FORM_SUBMISSION_FUNCTION.equals(formDataElement.getSubmitFlag())){
          WorkflowStep workflowStep = (WorkflowStep)workflowStepDAO.getSubmitStepByWorkflowRecordID(new Integer(formSubmissionForm.getWorkflowRecordID()));
          workflowStepID = workflowStep.getID();
        }
       }else{
         WorkflowStep workflowStep = (WorkflowStep)workflowStepDAO.getSubmitStepByWorkflowRecordID(new Integer(formSubmissionForm.getWorkflowRecordID()));
         workflowStepID = workflowStep.getID();
       }
     }
     String formSubmissionID = !Utility.isEmpty(formSubmissionForm.getID()) && !"null".equals(formSubmissionForm.getID()) ? formSubmissionForm.getID() : request.getParameter("formSubmissionID");
     FormPage formPage = null;
     List formPageList = formPageDAO.getDetailListByFormRecordIDStepID(formRecordID,workflowStepID);
     FormRecord formRecord = (FormRecord)formRecordDAO.getObjectByID(formRecordID);
     if (!Utility.isEmpty(formSubmissionID) && !"null".equals(formSubmissionID)){
       //FormSubmission formSubmission = (FormSubmission)formSubmissionDAO.getObjectByID(new Integer(request.getParameter("formSubmissionID")));
       //bill add for EIP-1241 start
       FormSubmission formSubmission = (FormSubmission)formSubmissionDAO.getObjectByID(new Integer(formSubmissionID));
      //bill add for EIP-1241 end
       formSubmissionForm.setFormData(formSubmission);
        //get the root ID
       Integer parentID = !(Utility.isEmpty(request.getParameter("dmsParentID")) && !"null".equals(request.getParameter("dmsParentID"))) ? new Integer(request.getParameter("dmsParentID")) : formSubmission.getDmsParentID();
       if(!Utility.isEmpty(parentID) && parentID.intValue() > 0 ){
         DmsDocument dms = (DmsDocument)dmsDocDAO.getObjectByID(parentID);
         String path = docRetrievalManager.getLocationPath(parentID);
         formSubmissionForm.setDmsParentID(parentID);
         formSubmissionForm.setDmsRootID(dms.getRootID());
         formSubmissionForm.setLocationPath(path);
       }
     }

//     formPageDAO.setMandatoryFromWFStep(formPageList);
     request.setAttribute("formPageListName",formPageList);
     request.setAttribute("formRecord",formRecord);
   } catch (ApplicationException appEx) {
     throw appEx;
   } catch (Exception e) {
     log.error(e, e);
     throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, e);
   } finally {}
 }

  public void insertRecord(ActionMapping mapping,
                          AbstractActionForm form,
                          HttpServletRequest request,
                          HttpServletResponse response)
     throws ApplicationException {
    List submitDataList = new ArrayList();

    try {
     MaintFormSubmissionForm formSubmissionForm = (MaintFormSubmissionForm)form;
     String opMode = (form!=null) ? form.getOpMode() : request.getParameter("opMode");
     //   check next due date
     if( FormSubmission.FORM_SUBMISSION_STATU_PENDING.equals(formSubmissionForm.getStatus())){
       String workflowRecordID = formSubmissionForm.getWorkflowRecordID();
       Integer workflowRecordIDInt = null;
       if(!Utility.isEmpty(workflowRecordID)){
        if(workflowRecordID.indexOf("|") <= 0 ){
            workflowRecordIDInt = TextUtility.parseIntegerObj(workflowRecordID);
         }else{

            workflowRecordIDInt = TextUtility.parseIntegerObj(workflowRecordID.substring(0,workflowRecordID.indexOf("|")));
         }
         String nextStepDueDate = formSubmissionForm.getNextStepDueDates();
         this.checkForWorkflow(workflowRecordIDInt,nextStepDueDate,this.getSessionContainer(request),this.getConnection(request));
       }
     }
     request.setAttribute("sViewPageNo","false"); // EditFormSubmission.jsp view next Page status.
     // Create From Submission
     FormSubmissionDAObject formSubmissionDAO = new FormSubmissionDAObject(this.getSessionContainer(request), this.getConnection(request));
     FormSubmission formSubmission = (FormSubmission)formSubmissionForm.getFormData();
     formSubmission.setIp(request.getRemoteAddr());
     formSubmission.setFormRecordID(formSubmission.getFormRecordID());
     Integer submissionID = formSubmission.getID();

     // Set the Status value.

     formSubmission.setStatus(formSubmissionForm.getStatus());

     int formPageNo = 0; // formPageNo is formPageList SeqNO,not formPage.getPageNo .
     String formRecordID = request.getParameter("formRecordID");

     if(!Utility.isEmpty(request.getParameter("formPageNo"))){
        formPageNo = Integer.parseInt(request.getParameter("formPageNo"));
     }
     FormDataElementDAObject formDataElementDAO = new FormDataElementDAObject(this.getSessionContainer(request), this.getConnection(request));
     FormPageDAObject formPageDAO = new FormPageDAObject(this.getSessionContainer(request), this.getConnection(request));
     List formPageList = formPageDAO.getDetailListByFormRecordID(new Integer(formRecordID));

     if(Utility.isEmpty(submissionID) && ("null".equals(request.getParameter("formSubmissionID")) || Utility.isEmpty(request.getParameter("formSubmissionID")))
            || GlobalConstant.OP_MODE_COPY.equals(opMode)){
       formSubmission = this.insertFormSubmission(formSubmission, form, request);
     }
     request.setAttribute("formSubmissionID", formSubmission.getID());

     if(!Utility.isEmpty(request.getParameter("progressID")) && !"null".equals(request.getParameter("progressID")) ){
       this.recordHandledForm(form, request);
     }

     List attrNames = Collections.list(request.getParameterNames());
     Integer seqNo = DataSourceFactory.getNextSequence("FORM_DATA_ELEMENT_SEQ_ID");

     for(int i=0;i<attrNames.size();i++){
       String attrName = (String)attrNames.get(i);
       String reqName = (String)attrNames.get(i);
       Integer pageID;
       Integer sectionID;

       if(attrName.startsWith("FB_FIELD_") || attrName.startsWith("FB_FILES_")){ //"displayFileNames_": if element type is file, then text field name is displayFileNames_. ){
         log.debug("Find Attribute:"+attrName+"\n");
         String[] parameterValues = request.getParameterValues(attrName);
         String elementID = "";
         // String elementSeq = "";
         // Get the PageID
         attrName = attrName.substring(9,attrName.length());
         pageID = Integer.valueOf(attrName.substring(0,attrName.indexOf("_")) );


         // Get the SectionID
         attrName = attrName.substring(attrName.indexOf("_")+1,attrName.length());
         sectionID = Integer.valueOf(attrName.substring(0,attrName.indexOf("_")));

         //       Get the elementID
         attrName = attrName.substring(attrName.indexOf("_")+1,attrName.length());

         if (attrName.indexOf("_") > 0) {
         elementID = attrName.substring(0,attrName.indexOf("_"));
         } else {
           elementID = attrName;
         }

           FormElementDAObject formElementDAO = new FormElementDAObject(this.getSessionContainer(request), this.getConnection(request));
           FormElement formElement = (FormElement)formElementDAO.getObjectByID(new Integer(elementID));
           //check field is uniqued.
           if (!Utility.isEmpty(formElement.getUniqueness()) && "Y".equals(formElement.getUniqueness())
               && !FormSubmission.FORM_SUBMISSION_STATU_DRAFT.equals(request.getParameter("submitFlag"))
                   && !Utility.isEmpty(request.getParameter(reqName))) {
             if(!formSubmissionDAO.isUniqueField(new Integer(elementID),request.getParameter(reqName),"")){
               throw new ApplicationException(ErrorConstant.FORM_SUBMISSION_DUPLICATE_FIELD_VALUE,null,formElement.getFieldName());
             }
           }
           FormDataDAObject formDataDAO = new FormDataDAObject(this.getSessionContainer(request), this.getConnection(request));

           FormDataElement formDataElement = new FormDataElement();
           formDataElement.setPageID(pageID);
           formDataElement.setSectionID(sectionID);
           formDataElement.setSubmissionID(formSubmission.getID());
           formDataElement.setElementID(Integer.valueOf(elementID));
           formDataElement.setSeq(seqNo);

           if (FormSubmission.FORM_SUBMISSION_STATU_DRAFT.equals(formSubmissionForm.getSubmitFlag())){
             formDataElement.setSubmitFlag(FormSubmission.FORM_SUBMISSION_STATU_DRAFT);
           }else{
             formDataElement.setSubmitFlag(FormSubmission.FORM_SUBMISSION_STATU_SAVED);
           }

           List dataList = new ArrayList();
           for(int j=0;j<parameterValues.length;j++){
             dataList.add(new FormData(Integer.valueOf(elementID),!Utility.isEmpty(parameterValues[j]) && !"null".equals(parameterValues[j]) ? parameterValues[j] :""));
           }
           formDataElement.setFormDataList(dataList);
           submitDataList.add(formDataElement);
           formDataElement = (FormDataElement)formDataElementDAO.insertObject(formDataElement);

           // Insert data into Form_Data
           List formDataList = formDataElement.getFormDataList();
           for(int k=0;k<formDataList.size();k++){
             FormData formData = (FormData)formDataList.get(k);
             formData.setDataElementID(formDataElement.getID());
             formDataDAO.insertObject(formData);
           }

           //if element type is file.
           // set the AttachmentList
           List totalAttachmentList = new ArrayList();
           String fileNameSeqNo = pageID.toString()+"_"+sectionID.toString()+"_"+elementID.toString();
           if ( !Utility.isEmpty(request.getParameter("fileNames_"+ fileNameSeqNo)) && !"null".equals(request.getParameter("fileNames_"+ fileNameSeqNo)) ) {
             com.dcivision.upload.core.MultipleFileUploadUtil uploadUtil = new com.dcivision.upload.core.MultipleFileUploadUtil(this.getSessionContainer(request));
             log.info("is again");
             log.info("formvalue is : "+request.getParameter("fileNames_"+fileNameSeqNo));
             List attachmentList = uploadUtil.getFormFileAttachmentList(request.getParameter("fileNames_"+fileNameSeqNo),WorkflowProgressAttachment.ATTACHED_SINGLE_FILE);
             if(!Utility.isEmpty(attachmentList)){
               totalAttachmentList.addAll(attachmentList);
             }
           }
           FormSubmissionManager formSubmissionManager = new FormSubmissionManager(this.getSessionContainer(request),this.getConnection(request));
           if (!Utility.isEmpty(request.getParameter("dmsFileNames_"+fileNameSeqNo)) && !"null".equals(request.getParameter("dmsFileNames_"+fileNameSeqNo))){
             List dmsAttachmentList = formSubmissionManager.getDmsDocumentAttachment(request.getParameter("dmsFileNames_"+fileNameSeqNo));
             if(!Utility.isEmpty(dmsAttachmentList)){
               totalAttachmentList.addAll(dmsAttachmentList);
             }
           }
           if (!Utility.isEmpty(totalAttachmentList)){
           log.info("totalAttachementList is not empty : size== "+totalAttachmentList.size());
            formSubmissionManager.createFormFileAttachments(totalAttachmentList,formDataElement.getID());
           }
       }
     }
     if (!Utility.isEmpty(formSubmission.getTrackID())) {
       formSubmissionForm.setTrackID(formSubmission.getTrackID().toString());
     }
     formSubmissionForm.setFormData(formSubmission);

     request.setAttribute("listSize", null);
     request.setAttribute("newFieldsSize",null);
     request.setAttribute("newField", null);

   } catch (ApplicationException appEx) {
     throw appEx;
   } catch (Exception e) {
     log.error(e, e);
     throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, e);
   } finally {}
  }

 public void updateRecord(ActionMapping mapping,
                          AbstractActionForm form,
                          HttpServletRequest request,
                          HttpServletResponse response)
     throws ApplicationException {
   SessionContainer sessionContainer = (SessionContainer) request.getSession().getAttribute(GlobalConstant.SESSION_CONTAINER_KEY);

   MaintFormSubmissionForm mainForm = (MaintFormSubmissionForm)form;
   String status = mainForm.getStatus();
   String oldStatus = "S";
   String formSubmissionID = request.getParameter("formSubmissionID");
   int adjustSeq = 0;
   List submitDataList = new ArrayList();
   try {
     MaintFormSubmissionForm formSubmissionForm = (MaintFormSubmissionForm)form;
     //   check next due date
     if( FormSubmission.FORM_SUBMISSION_STATU_PENDING.equals(formSubmissionForm.getStatus())){
       String workflowRecordID = formSubmissionForm.getWorkflowRecordID();
       Integer workflowRecordIDInt = null;
       if(!Utility.isEmpty(workflowRecordID)){
        if(workflowRecordID.indexOf("|") <= 0 ){
            workflowRecordIDInt = TextUtility.parseIntegerObj(workflowRecordID);
         }else{

            workflowRecordIDInt = TextUtility.parseIntegerObj(workflowRecordID.substring(0,workflowRecordID.indexOf("|")));
         }

         String nextStepDueDate = formSubmissionForm.getNextStepDueDates();
         this.checkForWorkflow(workflowRecordIDInt,nextStepDueDate,this.getSessionContainer(request),this.getConnection(request));
       }
     }
     request.setAttribute("sViewPageNo","false"); // EditFormSubmission.jsp view next Page status.
     // Create From Submission
     FormSubmissionDAObject formSubmissionDAO = new FormSubmissionDAObject(this.getSessionContainer(request), this.getConnection(request));
     FormSubmission formSubmission = (FormSubmission)formSubmissionDAO.getObjectByID(new Integer(formSubmissionID));

     //Get the old status
     oldStatus = formSubmission.getStatus() ;
     // Set the Status value.
     formSubmission.setStatus(formSubmissionForm.getStatus());
     formSubmission.setDmsParentID(formSubmissionForm.getDmsParentID());

     //get listFormDataElement and delete the Form_Data_Element and Form_Data table
     FormDataElementDAObject formDataElementDAO = new FormDataElementDAObject(this.getSessionContainer(request), this.getConnection(request));
     FormDataDAObject formDataDAO = new FormDataDAObject(this.getSessionContainer(request), this.getConnection(request));

     FormFileAttachmentDAObject formFileAttachmentDAO = new FormFileAttachmentDAObject(this.getSessionContainer(request), this.getConnection(request));
     List listFormDataElement =  formDataElementDAO.getListBySubmissionID(new Integer(formSubmissionID)) ;
     String[] formDataElementIDArr = new String[listFormDataElement.size()];

     List attrNames = Collections.list(request.getParameterNames());
     Integer seqNo = DataSourceFactory.getNextSequence("FORM_DATA_ELEMENT_SEQ_ID");
     FormElementDAObject elementDAO = new FormElementDAObject(this.getSessionContainer(request), this.getConnection(request));
     //Delete old data
     if (listFormDataElement.size() > 0){
        for (int j = 0; j < listFormDataElement.size(); j++) {
            FormDataElement formDataElement = (FormDataElement)
            listFormDataElement.get(j);
            boolean isEditElement = false;
            //get sectionID,if sectionID is not in attrNames, don't delete the section's elements.
            for(int i=0;i<attrNames.size();i++){
              String attrName = (String)attrNames.get(i);
              Integer pageID;
              Integer sectionID;
              Integer elementID;
              if(attrName.startsWith("FB_FIELD_")){
                String[] parameterValues = request.getParameterValues(attrName);
                // Get the PageID
                attrName = attrName.substring(9,attrName.length());
                pageID = Integer.valueOf(attrName.substring(0,attrName.indexOf("_")) );
                // Get the SectionID
                attrName = attrName.substring(attrName.indexOf("_")+1,attrName.length());
                sectionID = Integer.valueOf(attrName.substring(0,attrName.indexOf("_")));
                // Get the SectionSeq
                // attrName = attrName.substring(attrName.indexOf("_")+1,attrName.length());
                // Get the rowIndex
                // attrName = attrName.substring(attrName.indexOf("_")+1,attrName.length());
                // Get the elementID
                attrName = attrName.substring(attrName.indexOf("_")+1,attrName.length());
                if (attrName.indexOf("_") > 0) {
                elementID = Integer.valueOf(attrName.substring(0,attrName.indexOf("_")));
                } else {
                  elementID = Integer.valueOf(attrName);
                }

                if(elementID.intValue() == formDataElement.getElementID().intValue()){
                  isEditElement = true;
                }
              }
            }
            if(isEditElement){
              formDataElementIDArr[j] = formDataElement.getID().toString();
            }else{
              formDataElementIDArr[j] = "-1";
            }
        }
        if(formDataElementIDArr.length > 0){
          formDataElementDAO.deleteList(formDataElementIDArr);
          formDataDAO.deleteListByFormElementDataID(formDataElementIDArr);
        }
     }
     //Delete file attach data
     if (listFormDataElement.size() > 0){
        for (int j = 0; j < listFormDataElement.size(); j++) {
            FormDataElement formDataElement = (FormDataElement)
            listFormDataElement.get(j);
            boolean isEditElement = false;
            //get sectionID,if sectionID is not in attrNames, don't delete the section's elements.
            for(int i=0;i<attrNames.size();i++){
              String attrName = (String)attrNames.get(i);
              Integer pageID;
              Integer sectionID;
              Integer elementID;
              if(attrName.startsWith("FB_FILES_")){
                String[] parameterValues = request.getParameterValues(attrName);
                // Get the PageID
                attrName = attrName.substring(9,attrName.length());
                pageID = Integer.valueOf(attrName.substring(0,attrName.indexOf("_")) );
                // Get the SectionID
                attrName = attrName.substring(attrName.indexOf("_")+1,attrName.length());
                sectionID = Integer.valueOf(attrName.substring(0,attrName.indexOf("_")));
                // Get the SectionSeq
                // attrName = attrName.substring(attrName.indexOf("_")+1,attrName.length());
                // Get the rowIndex
                // attrName = attrName.substring(attrName.indexOf("_")+1,attrName.length());
                // Get the elementID
                attrName = attrName.substring(attrName.indexOf("_")+1,attrName.length());
                if (attrName.indexOf("_") > 0) {
                elementID = Integer.valueOf(attrName.substring(0,attrName.indexOf("_")));
                } else {
                  elementID = Integer.valueOf(attrName);
                }

                if(elementID.intValue() == formDataElement.getElementID().intValue()){
                  isEditElement = true;
                }
              }
              if(isEditElement){
                formDataElementIDArr[j] = formDataElement.getID().toString();
              }else{
                formDataElementIDArr[j] = "-1";
              }
            }
        }
        if(formDataElementIDArr.length > 0){
          formFileAttachmentDAO.deleteListByFormElementDataID(formDataElementIDArr);
        }
     }

     // Insert data into Form_Data_Element
     for(int i=0;i<attrNames.size();i++){
       String attrName = (String)attrNames.get(i);
       String reqName = (String)attrNames.get(i);

       Integer pageID;
       Integer sectionID;
       if(attrName.startsWith("FB_FIELD_") || attrName.startsWith("FB_FILES_")){
         log.debug("Find Attribute:"+attrName+"\n");
         String[] parameterValues = request.getParameterValues(attrName);
         String elementID = "";
         attrName = attrName.substring(9,attrName.length());
         pageID = Integer.valueOf(attrName.substring(0,attrName.indexOf("_")) );


         // Get the SectionID
         attrName = attrName.substring(attrName.indexOf("_")+1,attrName.length());
         sectionID = Integer.valueOf(attrName.substring(0,attrName.indexOf("_")));

         //       Get the elementID
         attrName = attrName.substring(attrName.indexOf("_")+1,attrName.length());
         if (attrName.indexOf("_") > 0) {
         elementID = attrName.substring(0,attrName.indexOf("_"));
         } else {
           elementID = attrName;
         }

         //       Check field is uniqued.
           FormElementDAObject formElementDAO = new FormElementDAObject(this.getSessionContainer(request), this.getConnection(request));
           FormElement formElement = (FormElement)formElementDAO.getObjectByID(new Integer(elementID));

           if (!Utility.isEmpty(formElement.getUniqueness()) && "Y".equals(formElement.getUniqueness())
                 && !FormSubmission.FORM_SUBMISSION_STATU_DRAFT.equals(request.getParameter("submitFlag"))
                     && !Utility.isEmpty(request.getParameter(reqName))) {
             boolean isCheckUniqueField = true;
             if (FormSubmission.FORM_SUBMISSION_STATU_SAVED.equals(formSubmissionForm.getStatus()) && (Utility.isEmpty(request.getParameter("progressID")) || "null".equals(request.getParameter("progressID")))){
               isCheckUniqueField = false;
             }
             if (isCheckUniqueField){
               if(!formSubmissionDAO.isUniqueField(new Integer(elementID),request.getParameter(reqName),formSubmissionID)){
                 throw new ApplicationException(ErrorConstant.FORM_SUBMISSION_DUPLICATE_FIELD_VALUE,null,formElement.getFieldName());
               }
             }
           }

           FormDataElement formDataElement = new FormDataElement();
           formDataElement.setPageID(pageID);
           formDataElement.setSectionID(sectionID);
           formDataElement.setSubmissionID(formSubmission.getID());
           formDataElement.setElementID(Integer.valueOf(elementID));

           if (FormSubmission.FORM_SUBMISSION_STATU_DRAFT.equals(formSubmissionForm.getSubmitFlag())){
             formDataElement.setSubmitFlag(FormSubmission.FORM_SUBMISSION_STATU_DRAFT);
           }else if ("FORMMONITOR".equals(request.getParameter("function"))){
             formDataElement.setSubmitFlag(FormSubmission.FORM_SUBMISSION_FUNCTION);
           }else {
             formDataElement.setSubmitFlag(FormSubmission.FORM_SUBMISSION_STATU_SAVED);
           }

           if (!Utility.isEmpty(request.getParameter("progressID")) && !"null".equals(request.getParameter("progressID"))){
              formDataElement.setWorkflowProgressID(new Integer(request.getParameter("progressID")));
           }

           List dataList = new ArrayList();
           for(int j=0;j<parameterValues.length;j++){
             dataList.add(new FormData(Integer.valueOf(elementID),!Utility.isEmpty(parameterValues[j]) && !"null".equals(parameterValues[j]) ? parameterValues[j] :""));
           }
           formDataElement.setFormDataList(dataList);
           formDataElement.setSeq(seqNo);
           submitDataList.add(formDataElement);
           formDataElement = (FormDataElement)formDataElementDAO.insertObject(formDataElement);

           // Insert data into Form_Data
           List formDataList = formDataElement.getFormDataList();

           for(int k=0;k<formDataList.size();k++){
             FormData formData = (FormData)formDataList.get(k);
             formData.setDataElementID(formDataElement.getID());
             formDataDAO.insertObject(formData);
             formDataList.set(k,formData);
           }
           // if element type is file.
           // set the AttachmentList
           List totalAttachmentList = new ArrayList();
           String fileNameSeqNo = pageID.toString()+"_"+sectionID.toString()+"_"+elementID.toString();
           if ( !Utility.isEmpty(request.getParameter("fileNames_"+ fileNameSeqNo)) && !"null".equals(request.getParameter("fileNames_"+ fileNameSeqNo))) {
             com.dcivision.upload.core.MultipleFileUploadUtil uploadUtil = new com.dcivision.upload.core.MultipleFileUploadUtil(this.getSessionContainer(request));
             List attachmentList = uploadUtil.getFormFileAttachmentList(request.getParameter("fileNames_"+fileNameSeqNo),WorkflowProgressAttachment.ATTACHED_SINGLE_FILE);
             if(!Utility.isEmpty(attachmentList)){
               totalAttachmentList.addAll(attachmentList);
             }
           }
           FormSubmissionManager formSubmissionManager = new FormSubmissionManager(this.getSessionContainer(request),this.getConnection(request));
           if (!Utility.isEmpty(request.getParameter("dmsFileNames_"+fileNameSeqNo)) && !"null".equals(request.getParameter("dmsFileNames_"+fileNameSeqNo))){
             List dmsAttachmentList = formSubmissionManager.getDmsDocumentAttachment(request.getParameter("dmsFileNames_"+fileNameSeqNo));
             if(!Utility.isEmpty(dmsAttachmentList)){
               totalAttachmentList.addAll(dmsAttachmentList);
             }
           }
           if (!Utility.isEmpty(totalAttachmentList)){
            formSubmissionManager.createFormFileAttachments(totalAttachmentList,formDataElement.getID());
           }
           /*
         }
         */

       }
     }
     formSubmissionForm.setFormData(formSubmission);
     //===== Save File to DMS ======
     FormSubmissionManager formSubmissionManager = new FormSubmissionManager(this.getSessionContainer(request), this.getConnection(request));
     Integer dmsParentID = !(Utility.isEmpty(request.getParameter("dmsParentID")) && !"null".equals(request.getParameter("dmsParentID"))) ? new Integer(request.getParameter("dmsParentID")) : null;
     formSubmission.setDmsParentID(dmsParentID);

     //Save Upload Location to FORM_SUBMISSION table.
     if ( (oldStatus.equals(FormSubmission.FORM_SUBMISSION_STATU_SAVED) ||
           oldStatus.equals(FormSubmission.FORM_SUBMISSION_STATU_PENDING) )
            &&(
         status.equals(FormSubmission.FORM_SUBMISSION_STATU_SAVED) ||
        status.equals(FormSubmission.FORM_SUBMISSION_STATU_PENDING) ||
        status.equals(FormSubmission.FORM_SUBMISSION_STATU_COMPLETED) ||
        status.equals(FormSubmission.FORM_SUBMISSION_STATU_SUBMIT ) ) ){
       //formSubmissionDAO.updateObject(formSubmission);
       FormSubmission tmpFormSubmission = this.insertFormSubmission(formSubmission, form, request);
       if (tmpFormSubmission!=null && null != (tmpFormSubmission.getTrackID()) ) {
          formSubmissionForm.setTrackID(tmpFormSubmission.getTrackID().toString());
       }
     }

     if(!Utility.isEmpty(request.getParameter("progressID")) && !"null".equals(request.getParameter("progressID")) ){
       this.recordHandledForm(form, request);
     }

     request.setAttribute("listSize", null);
     request.setAttribute("newFieldsSize",null);
     request.setAttribute("newField", null);
   } catch (ApplicationException appEx) {
     throw appEx;
   } catch (Exception e) {
     log.error(e, e);
     throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, e);
   } finally {}
  }


  public void executeWorkflowRoutine(ActionMapping mapping, WorkflowActionFormInterface form, HttpServletRequest request, HttpServletResponse response, String opMode, String navMode) throws ApplicationException {
    log.info("########## MaintFormSubmissionAction Workflow Routine Begin ##########");
    String workflowRecordID = request.getParameter("workflowRecordID");
    String workflowComment = request.getParameter("workflowComment");
    log.info("########## MaintFormSubmissionAction Workflow Routine End   ##########");
  }

  public void handleWorkflowRoutine(ActionMapping mapping,
                                    AbstractActionForm maintForm,
                                    HttpServletRequest request,
                                    HttpServletResponse response,
                                    String opMode,
                                    String navMode)
    throws ApplicationException {
    MaintFormSubmissionForm formSubmissionForm = (MaintFormSubmissionForm)maintForm;
    String status = formSubmissionForm.getStatus();
    if ( checkStartWorkflow(maintForm, request) ) {
      //formSubmissionForm.setObjParamMap(this.getObjParamMap(maintForm, request));
      super.handleWorkflowRoutine(mapping, formSubmissionForm, request, response, opMode, navMode);
    }

  }

  /**
   * check next due date.
   * @param workflowStepID
   * @param nextStepDueDate
   * @param sessionContainer
   * @param conn
   * @throws ApplicationException
   */
  private void checkForWorkflow(Integer workflowStepID,
        String nextStepDueDate,
        SessionContainer sessionContainer,
        Connection conn) throws ApplicationException {
    WorkflowStepManager wfStepManager = new WorkflowStepManager(sessionContainer,conn);
    wfStepManager.checkSecondStepDueDates(workflowStepID,nextStepDueDate);

  }

  private String getNewElementSeq(HttpServletRequest request,String deletePara, String elementSeq){
    int iElementSeq = Integer.parseInt(elementSeq);
    int adjustSeq = 0;
    for(int i=1;i<=iElementSeq;i++){
      String deleteParaI = deletePara+"_"+i;
      String tempSeq = request.getParameter(deleteParaI);
      if(Utility.isEmpty(tempSeq)){
        continue;
      } else {
        adjustSeq++;
      }
    }
    return (iElementSeq-adjustSeq)+"";
  }


  /**
   * Insert Form Submission.
   * @param formSubmission
   * @param request
   * @throws ApplicationException
   */
  private FormSubmission insertFormSubmission(FormSubmission formSubmission, AbstractActionForm form, HttpServletRequest request)throws ApplicationException {
    FormSubmissionDAObject formSubmissionDAO = new FormSubmissionDAObject(this.getSessionContainer(request), this.getConnection(request));
    FormRecordDAObject formRecordDAO = new FormRecordDAObject(this.getSessionContainer(request), this.getConnection(request));
    FormSubmission currentFormSubmission = null;
    Integer currentFormRecordID = formSubmission.getFormRecordID();
    String status = formSubmission.getStatus();
    MaintFormSubmissionForm submissionForm = (MaintFormSubmissionForm)form;
    String opMode = (submissionForm!=null) ? submissionForm.getOpMode() : request.getParameter("opMode");

    boolean hasFlow = false;
    if(!Utility.isEmpty(submissionForm.getWorkflowRecordID())){
      hasFlow = true;
    }

    //To Save a form
    if (FormSubmission.FORM_SUBMISSION_STATU_SAVED.equals(formSubmission.getStatus()) && !hasFlow ){
      if ((!Utility.isEmpty(formSubmission.getID()) && !"null".equals(formSubmission.getID())) && (!"null".equals(request.getParameter("formSubmissionID")) && !Utility.isEmpty(request.getParameter("formSubmissionID")))
                && !GlobalConstant.OP_MODE_COPY.equals(opMode)){
          formSubmission.setStatus(status);
          currentFormSubmission = (FormSubmission)formSubmissionDAO.updateObject(formSubmission);
      }else{
          currentFormSubmission = (FormSubmission)formSubmissionDAO.insertObject(formSubmission);
      }

    //To Submit a form
    } else {
      //No binding workflow to submit the form.(First Save, Second Submit)
      if(FormSubmission.FORM_SUBMISSION_STATU_COMPLETED.equals(submissionForm.getStatus()) && !Utility.isEmpty(formSubmission.getID())
            && !GlobalConstant.OP_MODE_COPY.equals(opMode)){
        currentFormSubmission = (FormSubmission)formSubmissionDAO.updateObject(formSubmission);

      //To Submit a form when do a task
      }else if("true".equals(request.getParameter("isSubmission")) ){
        currentFormSubmission = (FormSubmission)formSubmissionDAO.insertObject(formSubmission);

        //To Submit the first form
      } else if((Utility.isEmpty(formSubmission.getTrackID()) ||
          new Integer(0).equals(formSubmission.getTrackID()) ) ||
          GlobalConstant.OP_MODE_COPY.equals(opMode) ){
        Integer trackID = DataSourceFactory.getNextSequence("WORKFLOW_TRACK_ID");
        formSubmission.setTrackID(trackID);
        List formRecordList = formRecordDAO.getBindFormListByWorkflowRecordID(formSubmission.getWorkflowRecordID());
        if (!Utility.isEmpty(formRecordList)) {
          //To Insert the Form Submission with Workflow by Form (Single Form / Multi-Form)
          for(int i = 0; i < formRecordList.size(); i++){
            FormRecord formRecord = (FormRecord)formRecordList.get(i);
            FormSubmission tmpFormSubmission = formSubmission;
            if(formRecord.getID().equals(currentFormRecordID)){
              tmpFormSubmission.setFormRecordID(formRecord.getID());
              tmpFormSubmission.setStatus(status);
              currentFormSubmission = (FormSubmission)formSubmissionDAO.insertObject(tmpFormSubmission);
            } else {
              tmpFormSubmission.setDmsParentID(new Integer(0));
              tmpFormSubmission.setFormRecordID(formRecord.getID());
              tmpFormSubmission.setStatus(FormSubmission.FORM_SUBMISSION_STATU_PENDING);
              formSubmissionDAO.insertObject(tmpFormSubmission);
            }

          }
        } else {
          //To Insert the Form Submission with Workflow by Form Group
          currentFormSubmission = (FormSubmission)formSubmissionDAO.insertObject(formSubmission);
        }
        //To Submit the next Form, then update the status
      } else {
        formSubmission = (FormSubmission)formSubmissionDAO.getObjectByTrackIDFormRecordIDWorkflowRecordID(formSubmission.getTrackID(), formSubmission.getFormRecordID(), formSubmission.getWorkflowRecordID());
        formSubmission.setDmsParentID(submissionForm.getDmsParentID());
        if (FormSubmission.FORM_SUBMISSION_STATU_SUBMIT.equals(submissionForm.getStatus()) ||
            (!Utility.isEmpty(request.getAttribute("workflowStepID")) && !"null".equals(request.getAttribute("workflowStepID")) ) ) {
            // falcon_add_start
          String isStartStep=GlobalConstant.FALSE;
            WorkflowStepDAObject workflowStepDAO=new WorkflowStepDAObject(this.getSessionContainer(request),this.getConnection(request));
            WorkflowStep wfStep=(WorkflowStep)workflowStepDAO.getObjectByID(new Integer(request.getAttribute("workflowStepID").toString()));
               if(WorkflowStep.ACTION_TYPE_SUBMIT.equals(wfStep.getActionType())){
                isStartStep=GlobalConstant.TRUE;
              }
            if(GlobalConstant.TRUE.equals(isStartStep) && WorkflowProgress.STATUS_GENERAL_ACCOMPLISHMENT.equals(request.getParameter("isStartSubmit"))){
            formSubmission.setStatus(FormSubmission.FORM_SUBMISSION_STATU_SUBMIT);
            }
             // falcon_add_end
        }
        currentFormSubmission = (FormSubmission)formSubmissionDAO.updateObject(formSubmission);
        this.insertSystemObject(form, request);
      }
    }
    return currentFormSubmission;
  }

  /**
   * check whether start the workflow.
   * @param maintForm
   * @param request
   * @return
   * @throws ApplicationException
   */
  private boolean checkStartWorkflow(
        AbstractActionForm maintForm,
            HttpServletRequest request)
  throws ApplicationException {
    boolean startWorkflow = false;

    MaintFormSubmissionForm formSubmissionForm = (MaintFormSubmissionForm)maintForm;
    String wfRecordID = formSubmissionForm.getWorkflowRecordID();
    String trackID = formSubmissionForm.getTrackID();

    FormRecordDAObject formRecordDAO = new FormRecordDAObject(this.getSessionContainer(request), this.getConnection(request));

    //Form no bind with a workflow
    if(Utility.isEmpty(wfRecordID)){
      startWorkflow = false;
    } else {
      startWorkflow = true;
    }

    return startWorkflow ;
  }

  /**
   * get the object Parameter Map. put the multi-Form into a Hasp Map
   * @param maintForm
   * @param request
   * @return HashMap
   * @throws ApplicationException
   */
  private HashMap getObjParamMap(AbstractActionForm maintForm, HttpServletRequest request)throws ApplicationException {
    HashMap objParamMap = new HashMap();
    MaintFormSubmissionForm formSubmissionForm = (MaintFormSubmissionForm)maintForm;
    String trackID = formSubmissionForm.getTrackID();
    FormSubmissionDAObject formSubmissionDAO = new FormSubmissionDAObject(this.getSessionContainer(request), this.getConnection(request));

    List submitFormList = formSubmissionDAO.getListByTrackIDStatus(new Integer(trackID), FormSubmission.FORM_SUBMISSION_STATU_SUBMIT);

    for (int i = 0; i < submitFormList.size(); i++) {
      FormSubmission formSubmission = (FormSubmission)submitFormList.get(i);
      objParamMap.put(formSubmission.getID(), formSubmission);
    }

    return objParamMap;
  }

  /**
   * record the handle form in MTM_WF_Process_Access_Form table.
   * @param maintForm
   * @param request
   * @throws ApplicationException
   */
  private void recordHandledForm(AbstractActionForm maintForm, HttpServletRequest request)throws ApplicationException {
    MtmWfProgressAccessFormDAObject accessFormDAO = new MtmWfProgressAccessFormDAObject(this.getSessionContainer(request), this.getConnection(request));

    MaintFormSubmissionForm formSubmissionForm = (MaintFormSubmissionForm)maintForm;

    Integer workflowProgressID = new Integer(request.getParameter("progressID"));
    Integer formRecordID = new Integer(formSubmissionForm.getFormRecordID());
    Integer formSubmissionID = null;
    String processed = "";

    if(!Utility.isEmpty(request.getAttribute("formSubmissionID")) && !"null".equals(request.getAttribute("formSubmissionID")) ){
      formSubmissionID = new Integer(request.getAttribute("formSubmissionID").toString());
    } else {
      formSubmissionID = new Integer(request.getParameter("formSubmissionID"));
    }

    if("true".equals(request.getParameter("isSubmission"))){
      processed = WorkflowStep.FORM_PROCESS_PERMISSION_SUBMIT;
    } else {
      processed = WorkflowStep.FORM_PROCESS_PERMISSION_CHANGE;
    }

    MtmWfProgressAccessForm accessForm = new MtmWfProgressAccessForm();
    accessForm.setWorkflowProgressID(workflowProgressID);
    accessForm.setFormRecordID(formRecordID);
    accessForm.setFormSubmissionID(formSubmissionID);
    accessForm.setProcessed(processed);

    Object object = accessFormDAO.getObjectByWorkflowProgressIDFormRecordIDProcessedUserRecordID(
            accessForm.getWorkflowProgressID(),
            accessForm.getFormRecordID(),
            accessForm.getProcessed(),
            this.getSessionContainer(request).getUserRecordID());
    //check whether it is exist
    if(Utility.isEmpty(object)){
      accessFormDAO.insertObject(accessForm);
    }
  }


  private String getElementCount(HttpServletRequest request,String deletePara, String elementCount){
    int iElementCount = Integer.parseInt(elementCount);
    int adjustSeq = 0;
    for(int i=1;i<=iElementCount;i++){
      String deleteParaI = deletePara+"_"+i;
      String tempSeq = request.getParameter(deleteParaI);
      if(Utility.isEmpty(tempSeq)){
        continue;
      } else {
        adjustSeq++;
      }
    }
    return (iElementCount-adjustSeq)+"";
  }

  /**
   * get the URL of the next form to be submit.
   * @param request
   * @param trackID
   * @return
   * @throws ApplicationException
   */
  private String getNextTaskURL(
      HttpServletRequest request,
      Integer trackID,
      String oldFormRecordID ) throws ApplicationException{
    String nextTaskURL = null;
    FormSubmissionDAObject submissionDAO = new FormSubmissionDAObject(this.getSessionContainer(request), this.getConnection(request));
    FormRecordDAObject formRecordDAO = new FormRecordDAObject(this.getSessionContainer(request), this.getConnection(request));

    List submissionList = submissionDAO.getPendingListByTrackID(trackID );
    if( !Utility.isEmpty(submissionList)){
      FormSubmission formSubmission = null;
      for (int i=0; i < submissionList.size(); i++) {
        formSubmission = (FormSubmission)submissionList.get(i);
        if (!oldFormRecordID.equals(formSubmission.getFormRecordID().toString())) {
          break;
        }
      }
      if (!Utility.isEmpty(formSubmission)) {
        FormRecord formRecord = (FormRecord)formRecordDAO.getObjectByID(formSubmission.getFormRecordID());
        nextTaskURL = "MaintFormSubmission.do?" +
        "&navMode=N&function=FORMSUBMISSION" +
        "&trackID=" + formSubmission.getTrackID() +
        "&formRecordID=" + formSubmission.getFormRecordID() +
        "&workflowRecordID=" + formSubmission.getWorkflowRecordID() +
        "&oldFormRecordID=" + oldFormRecordID ;
      }
    }
    return nextTaskURL;
  }

  /**
   * generate the previous form update successfull message
   * @param request
   * @throws ApplicationException
   */
  private void generateMessage(
      HttpServletRequest request) throws ApplicationException{

    String oldFormRecordID = request.getParameter("oldFormRecordID");
    String updateMessage = null;
    if(!Utility.isEmpty(oldFormRecordID) && !"null".equals(oldFormRecordID)){
      FormRecordDAObject formDAO = new FormRecordDAObject(this.getSessionContainer(request), this.getConnection(request));
        Integer trackID = new Integer(request.getParameter("trackID"));
      FormRecord formRecord = (FormRecord)formDAO.getObjectByID( new Integer(oldFormRecordID) );
      updateMessage = MessageResourcesFactory.getMessage(this.getLocale(request),
          "form.message.form_record_submit_successfull",
          TextUtility.formatNumberWithZeroPrefix(SystemParameterFactory.getSystemParameterInteger(SystemParameterConstant.WORKLFLOW_TRACK_ID_FORMAT_LENGTH).intValue(), trackID),
          "[" + formRecord.getFormCode() + "] " + formRecord.getTitle() + " (" + formRecord.getFormVersion() + ") " );
      request.setAttribute("updateMessage", updateMessage);
    }

  }

  private void generateSaveDraftMessage(ActionForm form,
      HttpServletRequest request) throws ApplicationException{
    AbstractActionForm maintForm = (AbstractActionForm)form;
    MaintFormSubmissionForm formSubmissionForm = (MaintFormSubmissionForm)form;
    String opMode = (maintForm!=null) ? maintForm.getOpMode() : request.getParameter("opMode");
    String updateMessage = null;
    if (!Utility.isEmpty(opMode) && !"null".endsWith(opMode) && FormSubmission.FORM_SUBMISSION_STATU_SAVED.equals(formSubmissionForm.getStatus()) && !"FORMMONITOR".equals(request.getParameter("function"))){
      updateMessage = MessageResourcesFactory.getMessage(this.getLocale(request),
          "form.message.form_is_saved_in_Draft_List" ,updateMessage);
        request.setAttribute("saveDrafMessage", updateMessage);
    }
  }

  public ActionForward execute(ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
  throws ServletException {
    AbstractActionForm maintForm = (AbstractActionForm)form;
    MaintFormSubmissionForm formSubmissionForm = (MaintFormSubmissionForm)form;
    String opMode = (maintForm!=null) ? maintForm.getOpMode() : request.getParameter("opMode");    //maintForm.getOpMode();
    String navMode = (maintForm!=null) ? maintForm.getNavMode() : request.getParameter("navMode"); //maintForm.getNavMode();

    //get DAO
    WorkflowStepDAObject workflowStepDAO = new WorkflowStepDAObject(this.getSessionContainer(request), this.getConnection(request));
    FormPageDAObject formPageDAO = new FormPageDAObject(this.getSessionContainer(request), this.getConnection(request));
    FormSubmissionHtmlDAObject formSubmissionHtmlDAO = new FormSubmissionHtmlDAObject(this.getSessionContainer(request), this.getConnection(request));
    FormDataElementDAObject formDataElementDAO = new FormDataElementDAObject(this.getSessionContainer(request), this.getConnection(request));

    FormSubmissionManager formSubmissionManager = new FormSubmissionManager(this.getSessionContainer(request), this.getConnection(request));

    int formPageNo = 0; // formPageNo is formPageList SeqNO,not formPage.getPageNo .
    String formRecordID = request.getParameter("formRecordID");

    // falcon_add_start
    String formGroupID=request.getParameter("formGroupID");
    if(formRecordID==null || "null".equals(formRecordID)){
      formRecordID=(String)request.getAttribute("formRecordID");
    }
    if(formRecordID!=null && (formGroupID==null || "null".equals(formGroupID))){
      FormRecordDAObject formRecordDAO=new FormRecordDAObject(this.getSessionContainer(request), this.getConnection(request));
      FormRecord tmpFormRecord=(FormRecord)formRecordDAO.getByFormRecordID(formRecordID);
      formGroupID=tmpFormRecord.getFormGroupID().toString();
    }
    if(formRecordID!=null && formGroupID!=null){
      request.setAttribute("formRecordID", formRecordID);
      request.setAttribute("formGroupID", formGroupID);
    }
    // falcon_add_end

    if(!Utility.isEmpty(request.getParameter("formPageNo"))){
      formPageNo = Integer.parseInt(request.getParameter("formPageNo"));
    }

    if(!Utility.isEmpty(formSubmissionForm.getWorkflowRecordID()) && formSubmissionForm.getWorkflowRecordID().indexOf("|") > -1){
      String workflowRecordID = formSubmissionForm.getWorkflowRecordID().substring(0, formSubmissionForm.getWorkflowRecordID().indexOf("|"));
      formSubmissionForm.setWorkflowRecordID(workflowRecordID);
    }

    if(!Utility.isEmpty(formSubmissionForm.getWorkflowRecordID()) && !"null".equals(formSubmissionForm.getWorkflowRecordID())
                                                              && !"0".equals(formSubmissionForm.getWorkflowRecordID())
                                                              && !"-1".equals(formSubmissionForm.getWorkflowRecordID())){
      String workflowRecordID = formSubmissionForm.getWorkflowRecordID();
      String right=this.getSubmissionRight(request, response, workflowRecordID, this.getSessionContainer(request), this.getConnection(request));
      if (!Utility.isEmpty(right) && right.indexOf(WorkflowPermissionManager.EXECUTE_PERMISSION) >= 0) {
        request.setAttribute("ALLOW_EXECUTE", new Boolean(true));
      } else {
        ActionError error=new ActionError("common.label.no_access_right");
        ActionErrors errors=new ActionErrors();
        errors.add(null, error);
        this.saveErrors(request, errors);
        request.setAttribute("ALLOW_EXECUTE", new Boolean(false));
      }
    }
    Integer workflowStepID = !Utility.isEmpty(request.getParameter("workflowStepID")) && !"null".equals(request.getParameter("workflowStepID")) ? new Integer(request.getParameter("workflowStepID")) : new Integer(0);
    boolean isRightWorkflowStep = workflowStepID.intValue()==0
                                  && !Utility.isEmpty(formSubmissionForm.getWorkflowRecordID())
                                  && !"null".equals(formSubmissionForm.getWorkflowRecordID())
                                  && !"0".equals(formSubmissionForm.getWorkflowRecordID())
                                  && !"-1".equals(formSubmissionForm.getWorkflowRecordID());
    if (isRightWorkflowStep){
      if (!Utility.isEmpty(request.getParameter("formDataSeq")) && !"null".equals(request.getParameter("formDataSeq"))){
        FormDataElement formDataElement = (FormDataElement)formDataElementDAO.getFormDataElementBySeq(new Integer(request.getParameter("formDataSeq")));
        Integer progressID = formDataElement.getWorkflowProgressID();
        if (!Utility.isEmpty(progressID) && !"null".equals(progressID)){
          WorkflowStep workflowStep = (WorkflowStep)workflowStepDAO.getStepByWorkflowProgress(progressID);
          workflowStepID = workflowStep.getID();
        }else if(!Utility.isEmpty(formDataElement.getSubmitFlag()) && !FormSubmission.FORM_SUBMISSION_FUNCTION.equals(formDataElement.getSubmitFlag())){
          WorkflowStep workflowStep = (WorkflowStep)workflowStepDAO.getSubmitStepByWorkflowRecordID(new Integer(formSubmissionForm.getWorkflowRecordID()));
          workflowStepID = workflowStep.getID();
        }
      }else{
        WorkflowStep workflowStep = (WorkflowStep)workflowStepDAO.getSubmitStepByWorkflowRecordID(new Integer(formSubmissionForm.getWorkflowRecordID()));
        workflowStepID = workflowStep.getID();
      }
    }
    request.setAttribute("workflowStepID",workflowStepID);

    List formPageList = formPageDAO.getDetailListByFormRecordIDStepID(new Integer(formRecordID),workflowStepID);

    FormPage tempFormPage = (FormPage)formPageList.get(formPageNo);
    formPageID = tempFormPage.getID();

    //  from WF submit, set the function is WF function.
    if("WORKFLOW".equals(request.getParameter("submitFunction"))){
      super.setFunctionCode(SystemFunctionConstant.WORKFLOW_SUBMISSION);
    }else{
//  		super.setFunctionCode(SystemFunctionConstant.FORM_SUBMISSION);
      //allow user with only FORM_TRACK right to view the form
      super.setFunctionCode(SystemFunctionConstant.FORM_SUBMISSION + "||" + SystemFunctionConstant.FORM_TRACK+"||"+SystemFunctionConstant.WORKFLOW_SUBMISSION+"||"+SystemFunctionConstant.WORKFLOW_TRACK+"||"+SystemFunctionConstant.WORKFLOW_TASK+"||"+SystemFunctionConstant.WORKFLOW_MONITOR);
    }

    //Set the function code for current action.
    ActionForward forward = this.retrieveFunctionCode(request, response, mapping);
    if (forward!=null) {
      return forward;
    }


    boolean isHtml = false;
    try{
      FormSubmissionHtml formSubmissionHtml = (FormSubmissionHtml)formSubmissionHtmlDAO.getByRecordIDPageID(new Integer(formRecordID),formPageID);
      request.setAttribute("formSubmissionHtmlID",formSubmissionHtml.getID());
      isHtml = true;
    } catch (ApplicationException appEx) {
      if (ErrorConstant.DB_RECORD_NOT_FOUND_ERROR.equals(appEx.getMsgCode())) {
        isHtml = false;
      }
    }
    //hold the old status .
    String oldStatus = formSubmissionForm.getStatus();
    selectRecord(mapping, (AbstractActionForm) form, request, response);
    formSubmissionForm.setStatus(oldStatus);

    if (!isHtml) {
      if (!Utility.isEmpty(navMode) && (GlobalConstant.NAV_MODE_PREVIEW.equals(navMode) || FormSubmission.NAV_MODE_CON_VIEW_TRACKING.equals(navMode) )){
        maintForm.setNavMode(GlobalConstant.NAV_MODE_VIEW);
        return mapping.findForward(navMode);
      }
    }


    //Export file for WorkFlow or DMS
    if ("WORKFLOW".equals(request.getParameter("exportFunction")) || "DMS".equals(request.getParameter("exportFunction"))) {
      request.setAttribute("exportFunction",request.getParameter("exportFunction"));
      return mapping.findForward(FormSubmission.NAV_MODE_EXPORT);
    }

    if (GlobalConstant.OP_MODE_INSERT.equals(opMode) || GlobalConstant.OP_MODE_COPY.equals(opMode) ) {
      // Insert operation.
      try {
        if(!Utility.isEmpty(formSubmissionForm.getLocationPath())){
           String loginName = this.getSessionContainer(request).getUserRecord().getLoginName();
           String loginPsw = Crypt.decrypt(this.getSessionContainer(request).getUserRecord().getLoginPwd(), SystemParameterFactory.getSystemParameter(SystemParameterConstant.CRYPTO_SALT));
           String httpURL = SystemParameterFactory.getSystemParameter(SystemParameterConstant.APPLICATION_BASE_URL);
           FormHttpOperation formHttpOperation = new FormHttpOperation();
           formHttpOperation.login(httpURL + "/Login.do", loginName, loginPsw);
        }
        insertRecord(mapping, maintForm, request, response);
        this.handleWorkflowRoutine(mapping, maintForm, request, response, opMode, navMode);
        this.commit(request);
        //===== Save File to DMS ======
        if (FormSubmission.FORM_SUBMISSION_STATU_COMPLETED.equals(formSubmissionForm.getStatus())){
          formSubmissionManager.saveFileToDMS(new Integer(formSubmissionForm.getID()),request.getParameter("rootID"),request.getParameter("dmsParentID"),false);
          this.commit(request);
        }
        if (GlobalConstant.OP_MODE_COPY.equals(opMode)){
          addMessage(request, MESSAGE_RECORD_COPY);
          generateSaveDraftMessage(form,request);
        }else{
          addMessage(request, MESSAGE_RECORD_INSERT);
          generateSaveDraftMessage(form,request);
        }
      } catch (ApplicationException appEx1) {
        this.rollback(request);
        maintForm.setID(null);
        request.setAttribute("formSubmissionID", "");
        maintForm.setNavMode(GlobalConstant.NAV_MODE_NEW);
        handleApplicationException(request, appEx1);
      }

      if (isError(request)) {
        if (GlobalConstant.OP_MODE_COPY.equals(opMode)) {
          maintForm.setNavMode(GlobalConstant.NAV_MODE_CHANGE);
        } else {
          maintForm.setNavMode(GlobalConstant.NAV_MODE_NEW);
        }
        if (isHtml){
          return mapping.findForward(GlobalConstant.NAV_MODE_CHANGE);
        }else{
          return mapping.findForward(GlobalConstant.NAV_MODE_NEW);
        }
      } else {
        //===== For Handle The Second Step IS Dynamic Assign Owner Begin =======
        HashMap tmp = (HashMap) request.getAttribute("assignStepMap");
        if (tmp!=null && !tmp.isEmpty()) {
          maintForm.setNavMode(GlobalConstant.NAV_MODE_NEW);
          request.setAttribute("returnUrl",request.getContextPath()+"/form/ListFormSubmission.do");
          return mapping.findForward(WorkflowOperationConstant.WORKFLOW_ASSIGN_USER);
          //===== For Handle The Second Step IS Dynamic Assign Owner End   =======
        } else {
          //===== For Handle The Multi-Form Submit Begin ========
          //if it is multi-form binding with a workflow, after submit the first form,
          //to submit the next form.

          String trackID = formSubmissionForm.getTrackID();
          if (!Utility.isEmpty(trackID) && "FORMSUBMISSION".equals(request.getParameter("function"))) {
            String nextTaskURL = this.getNextTaskURL(request, new Integer(trackID), formSubmissionForm.getFormRecordID());
            if( !Utility.isEmpty(nextTaskURL) ){
              try{

                response.sendRedirect(nextTaskURL);
                return null;
              } catch(IOException ioex){
                log.error("response send redirect fail!");
              }
            }
          }
          //===== For Handle The Multi-Form Submit End   ========
          maintForm.setNavMode(GlobalConstant.NAV_MODE_VIEW);
          if (isHtml) {
            return mapping.findForward(GlobalConstant.NAV_MODE_CHANGE);
          }else{
            return mapping.findForward(GlobalConstant.NAV_MODE_VIEW);
          }
        }
      }
    }else if(GlobalConstant.OP_MODE_UPDATE.equals(opMode)){
      try{
        if(!Utility.isEmpty(formSubmissionForm.getLocationPath())){
           String loginName = this.getSessionContainer(request).getUserRecord().getLoginName();
           String loginPsw = Crypt.decrypt(this.getSessionContainer(request).getUserRecord().getLoginPwd(), SystemParameterFactory.getSystemParameter(SystemParameterConstant.CRYPTO_SALT));
           String httpURL = SystemParameterFactory.getSystemParameter(SystemParameterConstant.APPLICATION_BASE_URL);
           FormHttpOperation formHttpOperation = new FormHttpOperation();
           formHttpOperation.login(httpURL + "/Login.do", loginName, loginPsw);
        }
        updateRecord(mapping, (AbstractActionForm) form, request, response);
        this.handleWorkflowRoutine(mapping, maintForm, request, response, opMode, navMode);
        this.commit(request);
        //===== Save File to DMS ======
        if (FormSubmission.FORM_SUBMISSION_STATU_COMPLETED.equals(formSubmissionForm.getStatus())){
          formSubmissionManager.saveFileToDMS(new Integer(formSubmissionForm.getID()),request.getParameter("rootID"),request.getParameter("dmsParentID"),false);
          this.commit(request);
        }
        addMessage(request, MESSAGE_RECORD_UPDATE);
            generateSaveDraftMessage(form,request);
      }catch (ApplicationException appEx1) {
        this.rollback(request);
            maintForm.setID(null);
        maintForm.setNavMode(GlobalConstant.NAV_MODE_EDIT);
        handleApplicationException(request, appEx1);
      }
      if (isError(request)) {
        maintForm.setNavMode(GlobalConstant.NAV_MODE_EDIT);
        if (isHtml){
          return mapping.findForward(GlobalConstant.NAV_MODE_CHANGE);
        }else{
          return mapping.findForward(GlobalConstant.NAV_MODE_EDIT);
        }
      } else {
        //===== For Handle The Second Step IS Dynamic Assign Owner Begin =======
        HashMap tmp = (HashMap) request.getAttribute("assignStepMap");
        if (tmp!=null && !tmp.isEmpty()) {
          maintForm.setNavMode(GlobalConstant.NAV_MODE_NEW);
          request.setAttribute("returnUrl",request.getContextPath()+"/form/ListFormSubmission.do");
          return mapping.findForward(WorkflowOperationConstant.WORKFLOW_ASSIGN_USER);
          //===== For Handle The Second Step IS Dynamic Assign Owner End   =======
        } else {
          //===== For Handle The Multi-Form Submit Begin ========
          //if it is multi-form binding with a workflow, after submit the first form,
          //to submit the next form.
          String trackID = formSubmissionForm.getTrackID();
          if (!Utility.isEmpty(trackID) && "FORMSUBMISSION".equals(request.getParameter("function")) ) {
            String nextTaskURL = this.getNextTaskURL(request, new Integer(trackID), formSubmissionForm.getFormRecordID());
            if( !Utility.isEmpty(nextTaskURL) ){
              try{
                response.sendRedirect(nextTaskURL);
                return null;
              } catch(IOException ioex){
                log.error("response send redirect fail!");
              }
            }
          }
          //===== For Handle The Multi-Form Submit End   ========
          maintForm.setNavMode(GlobalConstant.NAV_MODE_VIEW);
          if (isHtml) {
            return mapping.findForward(GlobalConstant.NAV_MODE_CHANGE);
          }else{
            return mapping.findForward(GlobalConstant.NAV_MODE_VIEW);
          }
        }
      }
    }

    if (isHtml) {
      if (maintForm.getNavMode().equals(FormSubmission.NAV_MODE_CON_VIEW_TRACKING)){
        return mapping.findForward(FormSubmission.NAV_MODE_CON_VIEW_TRACKING);
      }else if(Utility.isEmpty(opMode) || maintForm.getNavMode().equals(GlobalConstant.NAV_MODE_VIEW) ){
        return mapping.findForward(GlobalConstant.NAV_MODE_CHANGE);
      }
    }

    //display the update message
    this.generateMessage(request);
    return super.execute(mapping, form, request, response);
  }

  /**
   * insert workflow progress system object record.
   * @param form
   * @param request
   * @throws ApplicationException
   */
  private void insertSystemObject(ActionForm form,
            HttpServletRequest request ) throws ApplicationException{
    MaintFormSubmissionForm recordForm = (MaintFormSubmissionForm)form;
    MtmWorkflowProgressSystemObjectDAObject progressObjectDAO =
        new MtmWorkflowProgressSystemObjectDAObject(this.getSessionContainer(request), this.getConnection(request));
    WorkflowProgressDAObject progressDAO = new WorkflowProgressDAObject(this.getSessionContainer(request), this.getConnection(request));

    WorkflowProgress progress = null;
    if(Utility.isEmpty(request.getParameter("progressID")) || "null".equals(request.getParameter("progressID")) ){
      progress = (WorkflowProgress)progressDAO.getFirstProgressByTrackID(new Integer(request.getParameter("trackID")));
    } else {
      progress = (WorkflowProgress)progressDAO.getObjectByID(new Integer(request.getParameter("progressID")));
    }

    Object object = progressObjectDAO.getObjectByTrackIDWorkflowProgressIDObjectID(
            new Integer(recordForm.getTrackID()), progress.getID(), recordForm.getFormData().getID());

    if (Utility.isEmpty(object)) {
      JobDataMap dataMap = new JobDataMap();
      dataMap.put("WORKFLOW_OBJECT", recordForm.getFormData());
      dataMap.put("WORKFLOW_PROGRESS", progress);
      dataMap.put("OBJECT_PARAMETER", recordForm.getObjParamMap());

      MtmWorkflowProgressSystemObject systemObject = new MtmWorkflowProgressSystemObject();
      systemObject.setBeanClassName(recordForm.getFormData().getClass().getName());
      systemObject.setObjectID(recordForm.getFormData().getID());
      systemObject.setTrackID(new Integer(recordForm.getTrackID()));
      systemObject.setWorkflowProgressID(progress.getID());
      systemObject.setParameterObject(dataMap.getWrappedMap());
      progressObjectDAO.insertObject(systemObject);
    }
  }

  public void deleteRecord(ActionMapping mapping,
      AbstractActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
  throws ApplicationException {
    MaintFormSubmissionForm maintForm = (MaintFormSubmissionForm)form;
    FormSubmissionDAObject formSubmissionDAO = new FormSubmissionDAObject(this.getSessionContainer(request), this.getConnection(request));
    FormDataElementDAObject formDataElementDAO = new FormDataElementDAObject(this.getSessionContainer(request), this.getConnection(request));
    FormDataDAObject formDataDAO = new FormDataDAObject(this.getSessionContainer(request), this.getConnection(request));
    FormFileAttachmentDAObject formFileAttachmentDAO = new FormFileAttachmentDAObject(this.getSessionContainer(request), this.getConnection(request));
    String formSubmissionID = !Utility.isEmpty(maintForm.getID()) && !"null".equals(maintForm.getID()) ? maintForm.getID() : request.getParameter("formSubmissionID");
    if (!Utility.isEmpty(formSubmissionID)&& !"null".equals(formSubmissionID)) {
      formSubmissionDAO.deleteObjectByID(new Integer(formSubmissionID));
      //delete Form_Data_Element and Form_Data and form_file_attachment table
      List listFormDataElement =  formDataElementDAO.getListBySubmissionID(new Integer(formSubmissionID)) ;
      String[] formDataElementIDArr = new String[listFormDataElement.size()];

      for (int j = 0; j < listFormDataElement.size(); j++) {
        FormDataElement formDataElement = (FormDataElement)listFormDataElement.get(j);
        formDataElementIDArr[j] = formDataElement.getID().toString();
      }

      if(formDataElementIDArr.length > 0){
        formDataElementDAO.deleteList(formDataElementIDArr);
        formDataDAO.deleteListByFormElementDataID(formDataElementIDArr);
        formFileAttachmentDAO.deleteListByFormElementDataID(formDataElementIDArr);
      }

    }
  }
  private String getSubmissionRight(HttpServletRequest request, HttpServletResponse response,String workflowRecordID,SessionContainer sessionContainer,Connection conn) throws ApplicationException {
    Integer userID = sessionContainer.getUserRecordID();
    String right = "";
      right = getSubmissionPermission(Integer.valueOf(workflowRecordID), userID, request);
    if(!Utility.isEmpty(right)){
      return right;
    }
    //check by delegation
    UserDelegationDAObject delegationDAO=new UserDelegationDAObject(sessionContainer,conn);
    List delegateList = delegationDAO.getListDelegatedToUser(userID);
    Iterator delegateIt=delegateList.iterator();
    while(delegateIt.hasNext()){
     UserDelegation tmpUserDelegation=(UserDelegation)delegateIt.next();
     Integer sourceID=tmpUserDelegation.getSourceUserID();
     right = getSubmissionPermission(Integer.valueOf(workflowRecordID), sourceID, request);
     if(!Utility.isEmpty(right)){
      return right;
       }
    }
    return right;
 }
  private String getSubmissionPermission(Integer workflowRecordID, Integer userID, HttpServletRequest request) throws ApplicationException {
    WorkflowStepDAObject wfStepDAO = new WorkflowStepDAObject(this.getSessionContainer(request), this.getConnection(request));
    WorkflowStep submitStep =(WorkflowStep) wfStepDAO.getSubmitStepByWorkflowRecordID(workflowRecordID);
    Integer submitStepID = submitStep.getID();
    WorkflowPermissionManager wfPermManager = new WorkflowPermissionManager(this.getSessionContainer(request), this.getConnection(request));
    String permissionValue = wfPermManager.getUserPermission4SpecialTask(submitStepID, null, userID);
    return permissionValue;
    }
}